-
Notifications
You must be signed in to change notification settings - Fork 49
Expose mechanisms in the high-level API #126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@@ -0,0 +1,180 @@ | |||
from gssapi.raw import oids as roids |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💪
gssapi/mechs.py
Outdated
It inherits from the low-level GSSAPI :class:`~gssapi.raw.oids.OID` class, | ||
and thus can be used with both low-level and high-level API calls. | ||
|
||
The functionality of this class is extended by RFC 5587 and RFC 5801. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't put this here, just put it in the method definitions
gssapi/mechs.py
Outdated
@property | ||
def sasl_name(self): | ||
""" | ||
Get the SASL name for the mechanism; depends on RFC 5801 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use requires-ext
to indicate RFC and extension requirements (e.g. https://github.com/cipherboy/python-gssapi/blob/4f91022e61a1e3c948313e4e4618dc92436183d6/gssapi/creds.py#L162)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(done)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
while you're doing updates, remove the "; depends on RFC 5801" -- just the requires-ext
tag below is fine.
gssapi/mechs.py
Outdated
|
||
class Mechanism(roids.OID): | ||
""" | ||
GSSAPI Mechanism |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpicky: "A GSSAPI Mechanism"
gssapi/mechs.py
Outdated
_sasl_name = None | ||
_mech_attrs = None | ||
|
||
def __init__(self, cpy=None, elements=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we definitely should fix this before merging...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because it's a C-based object, you actually need to override at least __new__
(and then __init__
if you want -- see the other objects in the high-level API).
gssapi/mechs.py
Outdated
from_oids(oids) | ||
Converts a list of OIDs into a set of Mechanisms | ||
""" | ||
return set(map(lambda mech: Mechanism(cpy=mech), oids)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... mech: cls(cpy=mech)...
gssapi/mechs.py
Outdated
raise NotImplementedError("Your GSSAPI implementation does not " | ||
"have support for RFC 5801") | ||
if self._sasl_name is None: | ||
self._sasl_name = rfc5801.inquire_saslname_for_mech(self) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We've generally opted to avoid caching unless necessary, so you should add a comment on why the caching is useful.
gssapi/mechs.py
Outdated
""" | ||
Get the SASL name for the mechanism; depends on RFC 5801 | ||
""" | ||
self._query_saslname() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self._saslname.sasl_mech_name
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(don't call the method and then rely on the cache directly -- just use whatever is returned from the method/property)
gssapi/mechs.py
Outdated
""" | ||
return rmisc.inquire_names_for_mech(self) | ||
|
||
def _query_saslname(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make this a property, and then use it as such.
gssapi/mechs.py
Outdated
|
||
m = rfc5801.inquire_mech_for_saslname(n) | ||
|
||
return Mechanism(m) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cls(m)
387543c
to
acc28ca
Compare
Thanks for the detailed review and the help tracking those issues down yesterday. :) I added TODO:
|
Hardcoding anything with a standard is fine in principle, but kind of defeats the point of calling into the GSSAPI there at all... I'm not decided on that. |
On second thought, I don't know if there is value to this. Both MIT and Heimdal support the RFC 5801 extensions, so mech_name will be available under both. Instead, I'd just make this PR conditional on RFC 5801 landing. |
9dc24ac
to
afd68bf
Compare
gssapi/mechs.py
Outdated
:requires-ext:`rfc5801` | ||
""" | ||
self._query_saslname() | ||
return self._query_saslname.mech_name.decode('UTF-8') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove this call entirely. I don't think we want to fall back to hard-coded stuff anyway.
gssapi/mechs.py
Outdated
""" | ||
base = self.dotted_form | ||
if rfc5801 is not None: | ||
base = "%s %s" % (self._query_saslname.mech_name.decode('UTF-8'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should look like <Mechanism Foo (1.2.3.4)>
or just <Mechanism (1.2.3.4)>
query_saslname is unavailable
gssapi/mechs.py
Outdated
|
||
:requires-ext:`rfc5801` | ||
""" | ||
self._query_saslname() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
redundant call
gssapi/mechs.py
Outdated
Get a list of all mechanisms supported by GSSAPI | ||
""" | ||
mechs = rmisc.indicate_mechs() | ||
return [cls(mech) for mech in mechs] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
collapse to (cls(mech) for mech in metchs)
gssapi/mechs.py
Outdated
raise NotImplementedError("Your GSSAPI implementation does not " | ||
"have support for RFC 5801") | ||
n = name | ||
if type(n) is not bytes: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use isinstance
5f46d74
to
44a0071
Compare
gssapi/mechs.py
Outdated
if issubclass(str, six.text_type): | ||
base = bytes(base, _utils._get_encoding()) | ||
else: | ||
base = bytes(base) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since dotted_form
returns a string, this needs to be cast to bytes
for python2 compatibility. However, python3 forces two arguments to bytes
, one of which is the encoding. Suggestions on how to make this better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it should be fine as
if isinstance(base, six.text_type):
base = base.encode(_utils._get_encoding())
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comments on the __bytes__
changes, otherwise seems good.
gssapi/raw/oids.pyx
Outdated
@@ -120,11 +132,15 @@ cdef class OID: | |||
if self._free_on_dealloc: | |||
free(self.raw_oid.elements) | |||
|
|||
def __bytes__(self): | |||
@property | |||
def byte_form(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
err... why is this necessary? Why not just leave it as __bytes__
?
gssapi/mechs.py
Outdated
def __unicode__(self): | ||
return self.__bytes__().decode(_utils._get_encoding()) | ||
|
||
def __bytes__(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm... I'd just leave __bytes__
as-is. Let in inherit from the low-level API for compatibility with OIDs -- some things might expect OID bytes when calling __bytes__
-- we shouldn't change that part of the API just because you're working Mechanisms.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
then put the "string form as bytes" in a separate private method (like _byte_desc
).
e40a67f
to
9566a39
Compare
Okie dokie, this is updated as well. In retrospect, not changing the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a few more nits.
gssapi/mechs.py
Outdated
if issubclass(str, six.text_type): | ||
base = bytes(base, _utils._get_encoding()) | ||
else: | ||
base = bytes(base) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it should be fine as
if isinstance(base, six.text_type):
base = base.encode(_utils._get_encoding())
gssapi/mechs.py
Outdated
@property | ||
def sasl_name(self): | ||
""" | ||
Get the SASL name for the mechanism; depends on RFC 5801 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
while you're doing updates, remove the "; depends on RFC 5801" -- just the requires-ext
tag below is fine.
gssapi/mechs.py
Outdated
"have support for RFC 5801") | ||
n = name | ||
if not isinstance(n, bytes): | ||
n = str(n).encode() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pattern we generally use here is
if isinstance(name, six.text_type):
name = name.encode(_utils._get_encoding())
See the gssapi/names.py
(at the bottom) for example
gssapi/tests/test_high_level.py
Outdated
s = str(mech) | ||
s.shouldnt_be_empty() | ||
s.should_be_a(str) | ||
s[0].shouldnt_be('<') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a fairly fragile line here. I'd just remove it, unless the SASL names are guaranteed to not begin with "<"...
gssapi/tests/test_high_level.py
Outdated
e = list(gssmechs.Mechanism.from_attrs(m_except=[attr])) | ||
|
||
count = len(i) + len(e) | ||
count.should_be(c) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(len(from_desired) + len(from_except)).should_be(c)
so we get a good error message like len(from_desired) + len(from_except) should be 37
.
gssapi/raw/oids.pyx
Outdated
@@ -61,6 +61,9 @@ cdef class OID: | |||
self._free_on_dealloc = True | |||
return 0 | |||
|
|||
def _copy_oid(self, OID other): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this doesn't seem to be needed any more
When constructing via a the cpy parameter, cpy would maintain ownership; if cpy._free_on_dealloc was set to true, the new object could have memory freed while still maintaining a reference to it. This fixes the issue by having the new object take ownership. To perform a memory copy, use the elements argument to the constructor. Signed-off-by: Alexander Scheel <[email protected]>
This introduces a new property, dotted_form, for querying the dotted form of the OID. Signed-off-by: Alexander Scheel <[email protected]>
bc994a6
to
c8e80b1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor nits (mostly doc-related) inline, otherwise looks good
gssapi/mechs.py
Outdated
return super(Mechanism, cls).__new__(cls, cpy, elements) | ||
|
||
@property | ||
def names(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should probably be name_types
, to be clearer -- we use the term name_type
elsewhere in the high-level API
gssapi/mechs.py
Outdated
@property | ||
def description(self): | ||
""" | ||
Get the description of the mechanism; depends on RFC 5801 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can remove depends on RFC 5801
, since you have the requires-ext
tag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto for the cases below
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, should've caught those sooner if I were thinking when I updated the PR.
gssapi/mechs.py
Outdated
@property | ||
def known_attrs(self): | ||
""" | ||
Get the known attributes of the mechanism; depends on RFC 5587 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should document what form an "attribute" takes.
gssapi/mechs.py
Outdated
@classmethod | ||
def all_mechs(cls): | ||
""" | ||
all_mechs() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for the explicit signature here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto below
gssapi/mechs.py
Outdated
""" | ||
from_attrs | ||
Get a generator of mechanisms supporting the specified attributes. See | ||
RFC 5587's indicate_mechs_by_attrs for more information. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
link to indicate_mechs_by_attrs
using the correct documentation tag (IIRC, it's something like :func:
).
This creates a new class, Mechanism, for inquiring information about a mechanism. This includes support for RFCs 5587 and 5801. As Mechanism derives from OID, it is compatible with all places that accept a mech by OID. Signed-off-by: Alexander Scheel <[email protected]> Signed-off-by: Alexander Scheel <[email protected]>
@property | ||
def attrs(self): | ||
""" | ||
Get the attributes of the mechanism; returns a set of OIDs ([OID]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leaving this open as I'm not sure if this is the desired format.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per IRC discussion with @DirectXMan12 this appears to be in the correct format.
@DirectXMan12 -- any new feedback would be appreciated. :) |
@DirectXMan12 friendly bump. 🐈 |
/me attempts to page this back into RAM |
Looks like my last comments were just around docs, so assuming past me's review was fairly thorough (I recall it being so), I'm going to merge this. |
This creates a new class, Mechanism, for inquiring
information about a mechanism. This includes support
for RFCs 5587 and 5801. As Mechanism derives from OID,
it is compatible with all places that accept a mech
by OID.
Points of discussion (mechs):
Fallback inmech_name()
: what mechs should we support? We could hard-code the three MIT/KRB5 OIDs (krb5/iakerb/spnego) with respective names for the fallback when RFC5801 is missing, but I'd like thoughts on that.Am I missing functions that significantly depend on a OID?init_sec_context
?Revising init() -- I wasn't able to get a call tosuper().__init__
to work like was done with creds. Thoughts would be appreciated.Regarding mech_attrs, I'm not yet sure how I want to handle that.
display_mech_attr
is about the only useful function I can see that depends on mech_attrs, and querying for a list of mech_attrs isn't trivial--It'd likely involve a call toindicate_mechs
+inquire_attrs_for_mechs
. I'm not really seeing a use for having mech_attrs as a class. Thoughts?